/* Definition for the system call handler function */

#include "dfs.h"
#include <minix/com.h>
#include <minix/callnr.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "neighbours.h"
#include "lfi.h"
#include "cache.h"
#include "param.h"


FORWARD _PROTOTYPE( char * crop_file_name, (char *path)				);

/* === DFS SYSTEM CALL HANDLERS === */
/*===========================================================================*
 *				do_dfs_get_cache_path			 *
 *===========================================================================*/
PUBLIC do_dfs_get_cache_path(){
	int r;
	vir_bytes src,dst;
	char key[NAME_MAX];
	char rep[PATH_MAX];
	
	/* if dfs server is not initialized the connection is going to be postponed */
	if (dfs_initialized != INIT) return(ERROR);
	
	/* initializing buffer*/
	memset(key,0,NAME_MAX);
	memset(rep,0,PATH_MAX);
	
	/* Get the file path */
	src = (vir_bytes) m_in.FILEALIAS;
	dst = (vir_bytes) key;
	
	/* do data copy */
	r = sys_datacopy(who_e, (vir_bytes) src, 
					 DFS_PROC_NR, (vir_bytes) dst,
					 m_in.FILEALIASLEN);
					 
    /* if anything bad happened return suddenly */
	printf("r = %d and %s\n",r,dst);
	if ( r!= OK) return (ERROR);
	
	/* check cache */
	r = belongs_to_cache(key,rep);
	printf("r = %d\n",r);
	if ( r!= OK) return (ERROR);
	
	/* do data copy */
	src = (vir_bytes) rep;
	dst = (vir_bytes) m_in.FILEPATH;
	
	r = sys_datacopy(DFS_PROC_NR, (vir_bytes) src, 
					 who_e, (vir_bytes) dst,
					 strlen(rep));
					
	if ( r!= OK) return (ERROR);
	printf("dfs : %s\n",rep);
	return (OK);
}
/*===========================================================================*
 *				do_dfs_set_cache_key			     *
 *===========================================================================*/
PUBLIC do_dfs_set_cache_key(){
	int r;
	vir_bytes src,dst;
	char key[NAME_MAX];
	char deleted_key[NAME_MAX];
	
	/* if dfs server is not initialized the connection is going to be postponed */
	if (dfs_initialized != INIT) return(ERROR);

	/* initializing buffer*/
	memset(key,0,NAME_MAX);
	memset(deleted_key,0,NAME_MAX);
	
	/* Get the file path */
	src = (vir_bytes) m_in.FILEALIAS;
	dst = (vir_bytes) key;
	
	/* do data copy */
	r = sys_datacopy(who_e, (vir_bytes) src, 
					 DFS_PROC_NR, (vir_bytes) dst,
					 m_in.FILEALIASLEN);
					 
    /* if anything bad happened return suddenly */
	if ( r!= OK) return (ERROR);
	
	/* insert to cache*/
	insert_to_cache(key,deleted_key);
	/* no key deleted */
	if(deleted_key == NULL) return (OK);
	
	/* do data copy */
	src = (vir_bytes) deleted_key;
	dst = (vir_bytes) m_in.FILEPATH;
	
	r = sys_datacopy(DFS_PROC_NR, (vir_bytes) src, 
					 who_e, (vir_bytes) dst,
					 strlen(deleted_key));
					
	if ( r!= OK) return (ERROR);
	printf("deleted_key : %s\n",deleted_key);
	
	
	return (OK);
}
/*===========================================================================*
 *				do_dfs_add_to_LFI			     *
 *===========================================================================*/
PUBLIC do_dfs_add_to_LFI()
{
	/* Variables to play with */
	int r,i,filesize;
	char file_to_index[PATH_MAX];
	vir_bytes src,dst;
	static int id_count;
	
	/* if dfs server is not initialized the connection is going to be postponed */
	if (dfs_initialized != INIT) return(ERROR);
	
	/* initializing buffer */
	memset(file_to_index,0,PATH_MAX);
	
	/* Checking path of file len */
	if (m_in.FILEPATHLEN <=0 || m_in.FILEPATHLEN > PATH_MAX) return(EINVAL);
	
	/* Get the file path */
	src = (vir_bytes) m_in.FILEPATH;
	dst = (vir_bytes) file_to_index;
	
	/* do data copy */
	r = sys_datacopy(who_e, (vir_bytes) src, 
					 DFS_PROC_NR, (vir_bytes) dst,
					 m_in.FILEPATHLEN);
	
	/* if anything bad happened return suddenly */
	if ( r!= OK) return (r);

    /* do add to LFI */
    r = add_to_lfi(crop_file_name(file_to_index),file_to_index);
	if (r==0) return (ERROR);
	
	return (OK);
	
}

/*===========================================================================*
 *				do_dfs_remove_from_LFI		 *
 *===========================================================================*/
PUBLIC do_dfs_remove_from_LFI()
{
    /* Variables to play with */
	int r,i,filesize;
	char file_alias[NAME_MAX];
	vir_bytes src,dst;
	static int id_count;
	
	/* if dfs server is not initialized the connection is going to be postponed */
	if (dfs_initialized != INIT) return(ERROR);
	
	/* initializing buffer */
	memset(file_alias,0,NAME_MAX);
	
	/* Checking path of file len */
	if (m_in.FILEALIASLEN <=0 || m_in.FILEALIASLEN > NAME_MAX) return(EINVAL);
	
	/* Get the file path */
	src = (vir_bytes) m_in.FILEALIAS;
	dst = (vir_bytes) file_alias;
	
	/* do data copy */
	r = sys_datacopy(who_e, (vir_bytes) src, 
					 DFS_PROC_NR, (vir_bytes) dst,
					 m_in.FILEALIASLEN);
	
	/* if anything bad happened return suddenly */
	if ( r!= OK) return (r);
	    
    /* do remove from LFI */
    r = remove_from_lfi(file_alias);

	if ( r== 0) return (ERROR);
	/* see ? */
	return(OK);

}

/*===========================================================================*
 *				do_dfs_get_LFI      		 *
 *===========================================================================*/
PUBLIC do_dfs_get_LFI()
{
	int r;
	char files[BUFFER_SIZE];
	vir_bytes src,dst;
	
	/* if dfs server is not initialized the connection is going to be postponed */
	if (dfs_initialized != INIT) return(ERROR);
	
	memset(files,0,sizeof(files));
	
	ls_lfi(files);
	
	if(files == NULL) return (ERROR);
	
	dst = (vir_bytes) m_in.FILES;
	src = (vir_bytes) files;
	
	/* do data copy */
	r = sys_datacopy(DFS_PROC_NR, (vir_bytes) src, 
					 who_e, (vir_bytes) dst,
					 strlen(files));
	
	/* if anything bad happened return suddenly */
	if ( r!= OK) return (r);
    return OK;
}

/*===========================================================================*
 *				do_dfs_get_filepath	    	 *
 *===========================================================================*/
PUBLIC do_dfs_get_file_path()
{
    int r;
	struct dfs_index res;
	char fa[NAME_MAX];
	vir_bytes src,dst;
    
    /* Checking len of file alias */
	if (m_in.FILEALIASLEN <=0 || m_in.FILEALIASLEN > NAME_MAX) return(EINVAL);
	
	/* init vars*/
	memset(fa,0,NAME_MAX);
	
	/* Get the file path */
	src = (vir_bytes) m_in.FILEALIAS;
	dst = (vir_bytes) fa;
	
	/* do data copy */
	r = sys_datacopy(who_e, (vir_bytes) src, 
					 DFS_PROC_NR, (vir_bytes) dst,
					 m_in.FILEALIASLEN);
					 
    /* if anything bad happened return suddenly */
	if ( r!= OK) return (ERROR);
    /* get entry from LFI */
    r = get_entry_from_lfi(fa,&res);
    
    /* check if there was no entry in LFI */
    if(r != OK) return (ERROR);
	
	src = (vir_bytes) res.filepath;
	dst = (vir_bytes) m_in.FILEPATH;

    /* do data copy backwards */
    r = sys_datacopy(DFS_PROC_NR, (vir_bytes) src,
                 who_e,(vir_bytes) dst,
                 strlen(res.filepath));
    /* if anything bad happened return suddenly */
	if (r!= OK) return (ERROR);
	
	return (OK);
}

/*===========================================================================*
 *				do_dfs_start			     *
 *===========================================================================*/
PUBLIC do_dfs_start()
{
	/* if DFS is initialized dont do anything. Return appropriate reply*/
	if(dfs_initialized == INIT){
		return ALREADYINIT;
	}
	/* Initializing DFS server */
	dfs_initialized = INIT;
	return(OK);		
}

/*===========================================================================*
 *				do_dfs_set_net_comp			     *
 *===========================================================================*/
PUBLIC do_dfs_set_net_comp()
{
	/* if DFS is initialized set the network components*/
	if(dfs_initialized != INIT) return(ERROR);
	
	/* set the vars */
	if(m_in.NETPID != 0)
		dfs_net_pid = m_in.NETPID;
			
	return(OK);		
}
/*===========================================================================*
 *				do_dfs_set_neighbour_address			     *
 *===========================================================================*/
PUBLIC do_dfs_set_neighbour_address()
{
	int r,len,i,sd;
	char ip[MAXIPADDRESSLEN];
	vir_bytes src,dst;
	
	/* if dfs server is not initialized the connection is going to be postponed */
	if (dfs_initialized != INIT) return(ERROR);
	
	/* initializing buffer */
	memset(ip,0,MAXIPADDRESSLEN);
	
	/* Get the ip Address */
	src = (vir_bytes) m_in.IPADDRESS;
	dst = (vir_bytes) ip;
	len = m_in.IPADDRESSLEN;
	sd =  m_in.SD;
	/* do data copy */
	r = sys_datacopy(who_e, (vir_bytes) src, 
					 DFS_PROC_NR, (vir_bytes) dst,
					 m_in.IPADDRESSLEN);
	
	/* if anything bad happened return suddenly */
	if ( r!= OK) return (r);
	
	r = add_to_neighbour_list(ip,m_in.SD);
	
	return r;		
}
/*===========================================================================*
 *				do_dfs_get_net_comp			     *
 *===========================================================================*/
PUBLIC do_dfs_get_net_comp()
{
	/* Problematic behaviour ... */
	return(OK);
}
/*===========================================================================*
 *				do_dfs_stop				     *
 *===========================================================================*/
PUBLIC do_dfs_stop()
{
	int r;
	/* if DFS is initialized dont do anything. Return appropriate reply*/
	if(dfs_initialized == NOTINIT) return(ERROR);
	
	/* Terminating DFS components by sending SIGUSR1 */
		
	r = kill(dfs_net_pid,SIGUSR1);
	if(r != OK) return(ERROR);
	dfs_net_pid = NOTSETCOMPONENT;
	
	/* Setting DFS to it's not initialized state */
	dfs_initialized = NOTINIT;
	return(OK);		
}

/* === UTILITY FUNCTIONS ===*/
  
/*===========================================================================*
 *				crop_file_name				     *
 *===========================================================================*/
PRIVATE char * crop_file_name(char *path)
{	/*Extracting file name in order to provide a nice alias for the file */
		int i;
		for(i=strlen(path)-1;i>0 && path[i-1] != '/';i--);
		return (path+i);
}

/*===========================================================================*
 *				no_sys				     *
 *===========================================================================*/
PUBLIC no_sys()
{
	/* A system call handler function for handling unimplemented system call requests */
	return(ENOSYS);
}
